import pandas as pd
import numpy as np
import random
import pickle

from sklearn.model_selection import GridSearchCV
#SVM虽然也支持输出各类的概率，但这需要额外的计算费用，且得到的概率也不保证是合法的概率，
#所以在这个例子中我们用正确率accuracy_score作为模型选择的度量，最后在最佳超参数情况下再训练模型，得到概率表示
from sklearn.metrics import accuracy_score
from matplotlib import pyplot as plt
from scipy.sparse import csr_matrix
from sklearn.model_selection import train_test_split
from sklearn.svm import LinearSVC
from sklearn.svm import SVC

dpath = './data/'
train1 = pd.read_csv(dpath +"Otto_FE_train_org.csv")
train2 = pd.read_csv(dpath +"Otto_FE_train_tfidf.csv")

#去掉多余的id
train2 = train2.drop(["id","target"], axis=1)
train =  pd.concat([train1, train2], axis = 1, ignore_index=False)
train.head()

del train1
del train2
print(train.shape)
y_train = train['target']   #形式为Class_x
X_train = train.drop(["id", "target"], axis=1)

#保存特征名字以备后用（可视化）
feat_names = X_train.columns

#sklearn的学习器大多之一稀疏数据输入，模型训练会快很多

X_train = csr_matrix(X_train)

X_train_part,X_val,y,y_val=train_test_split(X_train, y_train, train_size = 10000,test_size = 0.2,random_state = 0)
print (X_train_part.shape)
del train

#先对线性核试着进行调参，由于数据多比较慢就简单的只进行3折交叉验证
C_s = np.logspace(-1, 3, 5)
parameters={'C':C_s,}
lineSVC=LinearSVC(max_iter=2000)
grid=GridSearchCV(lineSVC,param_grid=parameters,cv=3,n_jobs=-1, return_train_score=True)
grid.fit(X_train_part,y)
print(grid.cv_results_)
print(grid.best_params_)
print("训练集评分：",grid.score(X_train_part,y))
print("测试集评分：",grid.score(X_val,y_val))

#打印图表，查看不同C对应的训练误差和交叉验证得到的测试误差的变化趋势。
plt.figure(1)
cv_result=grid.cv_results_
x=C_s = np.logspace(-1, 3, 5)
y1=cv_result['mean_train_score']
plt.title('mean_train_score')
plt.plot(x,y1)
plt.figure(2)
x=C_s = np.logspace(-1, 3, 5)
y2=cv_result['mean_test_score']
plt.title('mean_test_score')
plt.plot(x,y2)


bestLinearSVC = LinearSVC(C = 10,penalty='l2',dual=False)
bestLinearSVC.fit(X_train_part, y)

#保持模型，用于后续测试
pickle.dump(bestLinearSVC, open("Otto_LinearSVC.pkl", 'wb'))
plt.show()

#接下来训练rbf核的svc
gamma_s = np.logspace(-1, 1, 2)
C_s1 = np.logspace(-1, 1, 2)
parameters={'C':C_s1, 'gamma':[0.125,0.25,0.5,1,2,4]}

rbfSVC=SVC(kernel='rbf')
rbfgrid=GridSearchCV(rbfSVC,param_grid=parameters,cv=5,n_jobs=-1)

print(rbfgrid.fit(X_train_part, y))
print(rbfgrid.best_params_)
print("rbf核训练集评分：",rbfgrid.score(X_train_part,y))
print("rbf核测试集评分：",rbfgrid.score(X_val,y_val))
print(rbfgrid.cv_results_)
